"""
Trie（发音类似 "try"）或者说 前缀树 是一种树形数据结构，用于高效地存储和检索字符串数据集中的键。
这一数据结构有相当多的应用情景，例如自动补完和拼写检查。

请你实现 Trie 类：
Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word 。
boolean search(String word) 如果字符串 word 在前缀树中，返回 true（即，在检索之前已经插入）；否则，返回 false 。
boolean startsWith(String prefix) 如果之前已经插入的字符串word 的前缀之一为 prefix ，返回 true ；否则，返回 false 。
示例：
输入
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
输出
[null, null, true, false, true, null, true]
解释
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple");   // 返回 True
trie.search("app");     // 返回 False
trie.startsWith("app"); // 返回 True
trie.insert("app");
trie.search("app");     // 返回 True

链接：https://leetcode-cn.com/problems/implement-trie-prefix-tree
"""
from mode import collections


class Trie:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.child = collections.defaultdict(dict)

    def insert(self, word: str) -> None:
        """
        Inserts a word into the trie.
        """
        node = self.child
        for s in word:
            if s not in node.keys():
                node[s] = collections.defaultdict(dict)
            node = node[s]
        node['isEnd'] = True

    def search(self, word: str) -> bool:
        """
        Returns if the word is in the trie.
        """
        node = self.child
        for s in word:
            if s in node.keys():
                node = node[s]
            else:
                return False
        return node['isEnd'] == True

    def startsWith(self, prefix: str) -> bool:
        """
        Returns if there is any word in the trie that starts with the given prefix.
        """
        node = self.child
        for s in prefix:
            if s in node.keys():
                node = node[s]
            else:
                return False
        return True


class Trie1:
    def __init__(self):
        self.child = collections.defaultdict(dict)

    def insert(self, word: str) -> None:
        nowNode = self.child
        for s in word:
            if s not in nowNode.keys():
                nowNode[s] = collections.defaultdict(dict)  # 创建下一个节点
            nowNode = nowNode[s]
        nowNode['#'] = '#'  # 有一定的局限性 前提是单词里不能有结束符

    def search(self, word: str) -> bool:
        nowNode = self.child
        for s in word:
            if s in nowNode.keys():
                nowNode = nowNode[s]
            else:
                return False
        return '#' in nowNode.keys()

    def startsWith(self, prefix: str) -> bool:
        nowNode = self.child
        for s in prefix:
            if s in nowNode.keys():
                nowNode = nowNode[s]
            else:
                return False
        return True


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

if __name__ == "__main__":
    """
    ["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
    """
    word = 'app'
    A = Trie()
    A.insert(word)
    A.insert('word')
    print(A.search(word))
    print(A.startsWith('ap'))
